/**************************************************
 * Filename: Ssh.java
 * Version: v1.0
 * CreatedDate: 2011-5-7
 * Copyright (C) 2011 By cafebabe.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see http://www.gnu.org/licenses/.
 *
 * If you would like to negotiate alternate licensing terms, you may do
 * so by contacting the author: talentyao@foxmail.com
 ***************************************************/

package com.ywh.sshd;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.security.KeyPair;
import java.util.ArrayList;
import java.util.List;

import org.apache.sshd.ClientChannel;
import org.apache.sshd.ClientSession;
import org.apache.sshd.SshClient;
import org.apache.sshd.agent.AgentClient;
import org.apache.sshd.agent.AgentServer;
import org.apache.sshd.agent.SshAgent;
import org.apache.sshd.client.channel.ChannelShell;
import org.apache.sshd.common.keyprovider.FileKeyPairProvider;
import org.apache.sshd.common.util.NoCloseInputStream;
import org.apache.sshd.common.util.NoCloseOutputStream;

/**
 * 功能描述
 * 
 * @author cafebabe
 * @since 2011-5-7
 * @version 1.0
 */
public class Ssh {
	public static void main(String[] args) throws Exception {
		int port = 22;
		String host = "www.mystudio.tk";
		String login = "yaowenhao";
		boolean agentForward = false;
		List<String> command = new ArrayList<String>();
		command.add("uptime");
		boolean error = false;

		if (error) {
			System.err
					.println("usage: ssh [-A|-a] [-v[v][v]] [-l login] [-p port] hostname [command]");
			System.exit(-1);
		}

		// TODO: handle log level
		SshClient client = SshClient.setUpDefaultClient();
		client.start();

		try {
			boolean hasKeys = false;

			String authSock = System.getenv(SshAgent.SSH_AUTHSOCKET_ENV_NAME);
			if (authSock == null) {
				KeyPair[] keys = null;
				AgentServer server = new AgentServer();
				authSock = server.start();
				List<String> files = new ArrayList<String>();
				File f = new File("E:/kuaipan/工具/PuTTY/tkeys/",
						"cafebabe@githost");
				if (f.exists() && f.isFile() && f.canRead()) {
					files.add(f.getAbsolutePath());
				}
				// f = new File(System.getProperty("user.home"), ".ssh/id_rsa");
				// if (f.exists() && f.isFile() && f.canRead()) {
				// files.add(f.getAbsolutePath());
				// }
				try {
					if (files.size() > 0) {
						keys = new FileKeyPairProvider(
								files.toArray(new String[0])).loadKeys();
					}
				} catch (Exception e) {
				}
				SshAgent agent = new AgentClient(authSock);
				for (KeyPair key : keys) {
					agent.addIdentity(key, "");
				}
				agent.close();
			}
			if (authSock != null) {
				SshAgent agent = new AgentClient(authSock);
				hasKeys = agent.getIdentities().size() > 0;
			}
			client.getProperties().put(SshAgent.SSH_AUTHSOCKET_ENV_NAME,
					authSock);

			ClientSession session = client.connect(host, port).await()
					.getSession();
			int ret = ClientSession.WAIT_AUTH;

			while ((ret & ClientSession.WAIT_AUTH) != 0) {
				if (hasKeys) {
					session.authAgent(login);
					ret = session.waitFor(ClientSession.WAIT_AUTH
							| ClientSession.CLOSED | ClientSession.AUTHED, 0);
				} else {
					System.out.print("Password:");
					BufferedReader r = new BufferedReader(
							new InputStreamReader(System.in));
					String password = r.readLine();
					session.authPassword(login, password);
					ret = session.waitFor(ClientSession.WAIT_AUTH
							| ClientSession.CLOSED | ClientSession.AUTHED, 0);
				}
			}
			if ((ret & ClientSession.CLOSED) != 0) {
				System.err.println("error");
				System.exit(-1);
			}
			ClientChannel channel;
			if (command == null) {
				channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
				((ChannelShell) channel).setAgentForwarding(agentForward);
				channel.setIn(new NoCloseInputStream(System.in));
			} else {
				channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
				ByteArrayOutputStream baos = new ByteArrayOutputStream();
				Writer w = new OutputStreamWriter(baos);
				for (String cmd : command) {
					w.append(cmd).append(" ");
				}
				w.append("\n");
				w.close();
				System.out.println("command=" + baos.toString());
				channel.setIn(new ByteArrayInputStream(baos.toByteArray()));
			}
			channel.setOut(new NoCloseOutputStream(System.out));
			channel.setErr(new NoCloseOutputStream(System.err));
			channel.open().await();
			channel.waitFor(ClientChannel.CLOSED, 0);
			session.close(false);
		} finally {
			client.stop();
		}
	}

}
